#include "wlr-screencopy.h"

using namespace wayland;
using namespace wayland::detail;

const wl_interface *zwlr_screencopy_manager_v1_interface_capture_output_request[3] = {
    &zwlr_screencopy_frame_v1_interface,
    nullptr,
    &output_interface,
};

const wl_interface *zwlr_screencopy_manager_v1_interface_capture_output_region_request[7] = {
    &zwlr_screencopy_frame_v1_interface,
    nullptr,
    &output_interface,
    nullptr,
    nullptr,
    nullptr,
    nullptr,
};

const wl_interface *zwlr_screencopy_manager_v1_interface_destroy_request[0] = {};

const wl_message zwlr_screencopy_manager_v1_interface_requests[3] = {
    {
        "capture_output",
        "nio",
        zwlr_screencopy_manager_v1_interface_capture_output_request,
    },
    {
        "capture_output_region",
        "nioiiii",
        zwlr_screencopy_manager_v1_interface_capture_output_region_request,
    },
    {
        "destroy",
        "",
        zwlr_screencopy_manager_v1_interface_destroy_request,
    },
};

const wl_message zwlr_screencopy_manager_v1_interface_events[0] = {};

const wl_interface wayland::detail::zwlr_screencopy_manager_v1_interface =
    {
        "zwlr_screencopy_manager_v1",
        3,
        3,
        zwlr_screencopy_manager_v1_interface_requests,
        0,
        zwlr_screencopy_manager_v1_interface_events,
};

const wl_interface *zwlr_screencopy_frame_v1_interface_copy_request[1] = {
    &buffer_interface,
};

const wl_interface *zwlr_screencopy_frame_v1_interface_destroy_request[0] = {};

const wl_interface *zwlr_screencopy_frame_v1_interface_copy_with_damage_request[1] = {
    &buffer_interface,
};

const wl_interface *zwlr_screencopy_frame_v1_interface_buffer_event[4] = {
    nullptr,
    nullptr,
    nullptr,
    nullptr,
};

const wl_interface *zwlr_screencopy_frame_v1_interface_flags_event[1] = {
    nullptr,
};

const wl_interface *zwlr_screencopy_frame_v1_interface_ready_event[3] = {
    nullptr,
    nullptr,
    nullptr,
};

const wl_interface *zwlr_screencopy_frame_v1_interface_failed_event[0] = {};

const wl_interface *zwlr_screencopy_frame_v1_interface_damage_event[4] = {
    nullptr,
    nullptr,
    nullptr,
    nullptr,
};

const wl_interface *zwlr_screencopy_frame_v1_interface_linux_dmabuf_event[3] = {
    nullptr,
    nullptr,
    nullptr,
};

const wl_interface *zwlr_screencopy_frame_v1_interface_buffer_done_event[0] = {};

const wl_message zwlr_screencopy_frame_v1_interface_requests[3] = {
    {
        "copy",
        "o",
        zwlr_screencopy_frame_v1_interface_copy_request,
    },
    {
        "destroy",
        "",
        zwlr_screencopy_frame_v1_interface_destroy_request,
    },
    {
        "copy_with_damage",
        "2o",
        zwlr_screencopy_frame_v1_interface_copy_with_damage_request,
    },
};

const wl_message zwlr_screencopy_frame_v1_interface_events[7] = {
    {
        "buffer",
        "uuuu",
        zwlr_screencopy_frame_v1_interface_buffer_event,
    },
    {
        "flags",
        "u",
        zwlr_screencopy_frame_v1_interface_flags_event,
    },
    {
        "ready",
        "uuu",
        zwlr_screencopy_frame_v1_interface_ready_event,
    },
    {
        "failed",
        "",
        zwlr_screencopy_frame_v1_interface_failed_event,
    },
    {
        "damage",
        "2uuuu",
        zwlr_screencopy_frame_v1_interface_damage_event,
    },
    {
        "linux_dmabuf",
        "3uuu",
        zwlr_screencopy_frame_v1_interface_linux_dmabuf_event,
    },
    {
        "buffer_done",
        "3",
        zwlr_screencopy_frame_v1_interface_buffer_done_event,
    },
};

const wl_interface wayland::detail::zwlr_screencopy_frame_v1_interface =
    {
        "zwlr_screencopy_frame_v1",
        3,
        3,
        zwlr_screencopy_frame_v1_interface_requests,
        7,
        zwlr_screencopy_frame_v1_interface_events,
};

zwlr_screencopy_manager_v1_t::zwlr_screencopy_manager_v1_t(const proxy_t &p)
    : proxy_t(p)
{
    if (proxy_has_object() && get_wrapper_type() == wrapper_type::standard) {
        set_events(std::shared_ptr<detail::events_base_t>(new events_t), dispatcher);
        set_destroy_opcode(2U);
    }
    set_interface(&zwlr_screencopy_manager_v1_interface);
    set_copy_constructor([](const proxy_t &p) -> proxy_t {
        return zwlr_screencopy_manager_v1_t(p);
    });
}

zwlr_screencopy_manager_v1_t::zwlr_screencopy_manager_v1_t()
{
    set_interface(&zwlr_screencopy_manager_v1_interface);
    set_copy_constructor([](const proxy_t &p) -> proxy_t {
        return zwlr_screencopy_manager_v1_t(p);
    });
}

zwlr_screencopy_manager_v1_t::zwlr_screencopy_manager_v1_t(zwlr_screencopy_manager_v1 *p, wrapper_type t)
    : proxy_t(reinterpret_cast<wl_proxy *>(p), t)
{
    if (proxy_has_object() && get_wrapper_type() == wrapper_type::standard) {
        set_events(std::shared_ptr<detail::events_base_t>(new events_t), dispatcher);
        set_destroy_opcode(2U);
    }
    set_interface(&zwlr_screencopy_manager_v1_interface);
    set_copy_constructor([](const proxy_t &p) -> proxy_t {
        return zwlr_screencopy_manager_v1_t(p);
    });
}

zwlr_screencopy_manager_v1_t::zwlr_screencopy_manager_v1_t(proxy_t const &wrapped_proxy, construct_proxy_wrapper_tag /*unused*/)
    : proxy_t(wrapped_proxy, construct_proxy_wrapper_tag())
{
    set_interface(&zwlr_screencopy_manager_v1_interface);
    set_copy_constructor([](const proxy_t &p) -> proxy_t {
        return zwlr_screencopy_manager_v1_t(p);
    });
}

zwlr_screencopy_manager_v1_t zwlr_screencopy_manager_v1_t::proxy_create_wrapper()
{
    return {*this, construct_proxy_wrapper_tag()};
}

const std::string zwlr_screencopy_manager_v1_t::interface_name = "zwlr_screencopy_manager_v1";

zwlr_screencopy_manager_v1_t::operator zwlr_screencopy_manager_v1 *() const
{
    return reinterpret_cast<zwlr_screencopy_manager_v1 *>(c_ptr());
}

zwlr_screencopy_frame_v1_t zwlr_screencopy_manager_v1_t::capture_output(int32_t overlay_cursor, output_t const &output)
{
    proxy_t p = marshal_constructor(0U, &zwlr_screencopy_frame_v1_interface, nullptr, overlay_cursor, output.proxy_has_object() ? reinterpret_cast<wl_object *>(output.c_ptr()) : nullptr);
    return zwlr_screencopy_frame_v1_t(p);
}

zwlr_screencopy_frame_v1_t zwlr_screencopy_manager_v1_t::capture_output_region(int32_t overlay_cursor, output_t const &output, int32_t x, int32_t y, int32_t width, int32_t height)
{
    proxy_t p = marshal_constructor(1U, &zwlr_screencopy_frame_v1_interface, nullptr, overlay_cursor, output.proxy_has_object() ? reinterpret_cast<wl_object *>(output.c_ptr()) : nullptr, x, y, width, height);
    return zwlr_screencopy_frame_v1_t(p);
}

int zwlr_screencopy_manager_v1_t::dispatcher(uint32_t opcode, const std::vector<any> &args, const std::shared_ptr<detail::events_base_t> &e)
{
    return 0;
}

zwlr_screencopy_frame_v1_t::zwlr_screencopy_frame_v1_t(const proxy_t &p)
    : proxy_t(p)
{
    if (proxy_has_object() && get_wrapper_type() == wrapper_type::standard) {
        set_events(std::shared_ptr<detail::events_base_t>(new events_t), dispatcher);
        set_destroy_opcode(1U);
    }
    set_interface(&zwlr_screencopy_frame_v1_interface);
    set_copy_constructor([](const proxy_t &p) -> proxy_t {
        return zwlr_screencopy_frame_v1_t(p);
    });
}

zwlr_screencopy_frame_v1_t::zwlr_screencopy_frame_v1_t()
{
    set_interface(&zwlr_screencopy_frame_v1_interface);
    set_copy_constructor([](const proxy_t &p) -> proxy_t {
        return zwlr_screencopy_frame_v1_t(p);
    });
}

zwlr_screencopy_frame_v1_t::zwlr_screencopy_frame_v1_t(zwlr_screencopy_frame_v1 *p, wrapper_type t)
    : proxy_t(reinterpret_cast<wl_proxy *>(p), t)
{
    if (proxy_has_object() && get_wrapper_type() == wrapper_type::standard) {
        set_events(std::shared_ptr<detail::events_base_t>(new events_t), dispatcher);
        set_destroy_opcode(1U);
    }
    set_interface(&zwlr_screencopy_frame_v1_interface);
    set_copy_constructor([](const proxy_t &p) -> proxy_t {
        return zwlr_screencopy_frame_v1_t(p);
    });
}

zwlr_screencopy_frame_v1_t::zwlr_screencopy_frame_v1_t(proxy_t const &wrapped_proxy, construct_proxy_wrapper_tag /*unused*/)
    : proxy_t(wrapped_proxy, construct_proxy_wrapper_tag())
{
    set_interface(&zwlr_screencopy_frame_v1_interface);
    set_copy_constructor([](const proxy_t &p) -> proxy_t {
        return zwlr_screencopy_frame_v1_t(p);
    });
}

zwlr_screencopy_frame_v1_t zwlr_screencopy_frame_v1_t::proxy_create_wrapper()
{
    return {*this, construct_proxy_wrapper_tag()};
}

const std::string zwlr_screencopy_frame_v1_t::interface_name = "zwlr_screencopy_frame_v1";

zwlr_screencopy_frame_v1_t::operator zwlr_screencopy_frame_v1 *() const
{
    return reinterpret_cast<zwlr_screencopy_frame_v1 *>(c_ptr());
}

void zwlr_screencopy_frame_v1_t::copy(buffer_t const &buffer)
{
    marshal(0U, buffer.proxy_has_object() ? reinterpret_cast<wl_object *>(buffer.c_ptr()) : nullptr);
}

void zwlr_screencopy_frame_v1_t::copy_with_damage(buffer_t const &buffer)
{
    marshal(2U, buffer.proxy_has_object() ? reinterpret_cast<wl_object *>(buffer.c_ptr()) : nullptr);
}

bool zwlr_screencopy_frame_v1_t::can_copy_with_damage() const
{
    return (get_version() >= copy_with_damage_since_version);
}

std::function<void(shm_format, uint32_t, uint32_t, uint32_t)> &zwlr_screencopy_frame_v1_t::on_buffer()
{
    return std::static_pointer_cast<events_t>(get_events())->buffer;
}

std::function<void(zwlr_screencopy_frame_v1_flags)> &zwlr_screencopy_frame_v1_t::on_flags()
{
    return std::static_pointer_cast<events_t>(get_events())->flags;
}

std::function<void(uint32_t, uint32_t, uint32_t)> &zwlr_screencopy_frame_v1_t::on_ready()
{
    return std::static_pointer_cast<events_t>(get_events())->ready;
}

std::function<void()> &zwlr_screencopy_frame_v1_t::on_failed()
{
    return std::static_pointer_cast<events_t>(get_events())->failed;
}

std::function<void(uint32_t, uint32_t, uint32_t, uint32_t)> &zwlr_screencopy_frame_v1_t::on_damage()
{
    return std::static_pointer_cast<events_t>(get_events())->damage;
}

std::function<void(uint32_t, uint32_t, uint32_t)> &zwlr_screencopy_frame_v1_t::on_linux_dmabuf()
{
    return std::static_pointer_cast<events_t>(get_events())->linux_dmabuf;
}

std::function<void()> &zwlr_screencopy_frame_v1_t::on_buffer_done()
{
    return std::static_pointer_cast<events_t>(get_events())->buffer_done;
}

int zwlr_screencopy_frame_v1_t::dispatcher(uint32_t opcode, const std::vector<any> &args, const std::shared_ptr<detail::events_base_t> &e)
{
    std::shared_ptr<events_t> events = std::static_pointer_cast<events_t>(e);
    switch (opcode) {
    case 0:
        if (events->buffer)
            events->buffer(shm_format(args[0].get<uint32_t>()), args[1].get<uint32_t>(), args[2].get<uint32_t>(), args[3].get<uint32_t>());
        break;
    case 1:
        if (events->flags)
            events->flags(zwlr_screencopy_frame_v1_flags(args[0].get<uint32_t>()));
        break;
    case 2:
        if (events->ready)
            events->ready(args[0].get<uint32_t>(), args[1].get<uint32_t>(), args[2].get<uint32_t>());
        break;
    case 3:
        if (events->failed)
            events->failed();
        break;
    case 4:
        if (events->damage)
            events->damage(args[0].get<uint32_t>(), args[1].get<uint32_t>(), args[2].get<uint32_t>(), args[3].get<uint32_t>());
        break;
    case 5:
        if (events->linux_dmabuf)
            events->linux_dmabuf(args[0].get<uint32_t>(), args[1].get<uint32_t>(), args[2].get<uint32_t>());
        break;
    case 6:
        if (events->buffer_done)
            events->buffer_done();
        break;
    }
    return 0;
}

const bitfield<1, 1> zwlr_screencopy_frame_v1_flags::y_invert{1};
